/* 
 * @moduleName: InnerFoemSchema.js
 * @Desc: 这个函数用来划分schema表 来区分不同的结构
 * @Author: djkloop 
 * @Date: 2017-11-29 15:49:45 
 * @Last Modified by: djkloop
 * @Last Modified time: 2017-12-21 00:25:50
 */
import React from 'react';
import {uploaderUtil,selectUtil,cascaderUtil, radioUtil,normalUtil, checkboxUtil,multiselectUtil,betweenUtil} from './DBFormRenderUtils'
import {
  Form,
  Row,
} from 'antd';
import Logger from '../../utils/Logger'
import FormConfig from '../../DBUtils/DBUtils'
Logger.getLogger('InnerFormSchema')


// 暂存每个表对应的schema callback, 解析schema是个代价较大的操作, 应该尽量复用
const schemaMap = new Map();
// 暂存每个表对应的表单组件, key是表名, value是对应的react组件
const formMap = new Map();
// 把进入当前的type值拿到
const typeComponent = new Map();
// 这里来个hoc美滋滋 之后再让antd包一层...
const hocTmp = (tableName,schema,_this,ignoreCache, type) => {
  return class tmpComponent extends React.Component {
    componentWillMount() {
      const schemaCallback = _this.parse(schema)
      if (!ignoreCache) {
        schemaMap.set(tableName, schemaCallback);
      }
      this.schemaCallback = schemaCallback;
    }
    // 拿到值去设置啊 真他么神了
    // 这种方法都能想到, 我tm都佩服自己...
    componentDidMount(){
      if (this.props.initData) {
        let _resObj = {}
        for (const key in this.props.initData) {
          if(key !== '__v') {
            _resObj[key] = this.props.initData[key]
          }
        }
        this.props.form.setFieldsValue(FormConfig.transformRawTimeToObject(_resObj));
      }
    }
    render() {
      return this.schemaCallback(this.props.form.getFieldDecorator, this.props.forUpdate, this.props.keysToUpdate);
    }
  }
}

const SchemaUtils = {
  getForm(tableName, schema, type) {
    // 是否忽略缓存
    typeComponent.set('type', type)
    const ignoreCache = FormConfig.shouldIgnoreSchemaCache(tableName)
    // 这个缓存 
    const newForm = this.createForm(tableName, schema);
    if (!ignoreCache) {
      formMap.set(tableName, newForm);
    }
    return newForm;
  },
  createForm(tableName, schema, type) {
    const ignoreCache = FormConfig.shouldIgnoreSchemaCache(tableName)
    const _this = this;
    // 这个地方和原版本有区别
    return Form.create({})(hocTmp(tableName,schema,_this,ignoreCache,type))
  },
  parse(schema) {
    const rows = []
    let cols = []
    const type = typeComponent.get('type')
    let spaceLeft = 24;
    // 总共24格 单输入框 一行三个
    // 范围选择器 一行最多两个
    schema.forEach(field => {
      let spaceNeed = 8
      
      // 如果不显示把这行干掉 新增单页面不需要隐藏字段！
      if(field.showInForm === false && type !== 'single') {
        spaceNeed = 24;
        return
      }
      
      // 范围选择真是个很尴尬的东西
      // 日期 一行只能放两个 
      if (field.showType === 'between' && field.dataType === 'datetime') {
        spaceNeed = 8;
      } 
      
      // 范围
      if(field.showType === 'between' && field.dataType === 'datetimeRange') {
        spaceNeed = 12
      }

      // 上传 一行只能放一个
      if(field.showType && field.showType.indexOf('Uploade-') !== -1) {
        spaceNeed = 24
      }

      // 如果当前行空间不足, 就换行
      if (spaceLeft < spaceNeed) {
        rows.push(cols);
        cols = [];  // 重置cols
        spaceLeft = 24;  // 剩余空间重置
      }
      // 这个地方和
      if(field.showType && field.showType.indexOf('Uploade-') !== -1) {
        switch (field.showType) {
          case 'Uploade-image': 
            cols.push(uploaderUtil.transformUploader(field,type))
            break;
          case 'Uploade-file':
            cols.push(uploaderUtil.transformUploader(field,type))
            break;
          default: 
            console.log(2)  
            break;
        }
      } else {
        // 这里要根据antd提供的类型用自己函数来解析schema
        switch (field.showType) {
          case 'select':
            cols.push(selectUtil.transformSelect(field,type))
            break;
          case 'radio':
            cols.push(radioUtil.transformRadio(field,type))
            break;
          case 'checkbox':
            cols.push(checkboxUtil.transformCheckBox(field,type))
            break;
          case 'multiSelect':
            cols.push(multiselectUtil.transformMultiSelect(field,type))
            break;
            case 'between':
            cols.push(betweenUtil.transformBetween(field,type));
            break;
          case 'cascader':
            cols.push(cascaderUtil.transformCascader(field,type));
            break;
          default:
            cols.push(normalUtil.transformNormal(field,type));
        }
      }
      spaceLeft -= spaceNeed
    })
    // 别忘了最后一行
    if (cols.length > 0) {
      rows.push(cols);
    }

    // 至此, schema解析完毕, 接下来是回调函数
    // 这里有一点闭包的概念
    return (getFieldDecorator, forUpdate, keysToUpdate) => {
      const formRows = []; // 最终的表单中的一行
      for (let i = 0; i < rows.length; i++) {
        const formCols = [];  // 最终的表单中的一列
        for (const row of rows[i]) {
          formCols.push(row(getFieldDecorator, forUpdate, keysToUpdate));  // 注意这里的col是一个函数
        }
        formRows.push(<Row key={i} gutter={24}>{formCols}</Row>);
      }
      return (
      <Form layout="horizontal">
        {formRows}
      </Form>);
    };
  }
}

export default SchemaUtils


